home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / freeWAIS-sf-1.1 / ui / swais.c < prev    next >
C/C++ Source or Header  |  1995-01-09  |  71KB  |  2,498 lines

  1. /* WIDE AREA INFORMATION SERVER SOFTWARE:
  2.    No guarantees or restrictions.  See the readme file for the full standard
  3.    disclaimer.
  4. */
  5.  
  6. /* Copyright (c) CNIDR (see ../COPYRIGHT) */
  7.  
  8.  
  9. /* This is a simple screen user interface for making WAIS queries
  10.  * It is the strange offspring of waisq and curses..
  11.  *
  12.  * Revision 1.2 initial version by jcurran@nnsc.nsf.net 
  13.  *   (dedicated to Suzi, Alex, et. al.)          
  14.  *
  15.  * Revision 1.5 changes 12/91 by datta@cs.uwp.edu
  16.  *
  17.  *   added page up/down 'J/K'
  18.  *   screen state now returns to normal after piping commands
  19.  *   added mail 'm' option 
  20.  *   fixed number entry on source selection to allow for up to MAXINT sources
  21.  *   there is now a pause after viewing a document so if the pager is 'more'
  22.  *         the user will not miss the last screen.
  23.  *
  24.  * Revision 1.6 changes 01/92 by jcurran@nnsc.nsf.net
  25.  *
  26.  *   fixed common_wais_dir on help message
  27.  *   change default common dir to /usr/lib/wais-sources
  28.  *   fix formatting for >99 sources
  29.  *   add ^v aliases for page down, <esc>v for page up
  30.  *   add "/" (find) to find source
  31.  *   add "/" (find) to find result
  32.  *   simplify <return> processing for users
  33.  *   changed the view source information to pipe through $PAGER or 'more'
  34.  *         to allow the use of source descriptions larger than 1 screen.
  35.  *         (done by datta@cs.uwp.edu)
  36.  * 
  37.  * Revision 1.7 changes 01/92 by jcurran@nnsc.nsf.net
  38.  *
  39.  *   fixed miscellaneous selection bugs
  40.  *   added option processing and option screen
  41.  *
  42.  * Revision 1.12 changes 07/92 by warnock@hypatia.gsfc.nasa.gov
  43.  *
  44.  *   added patch from comp.infosystems.wais to add elm-like cursor paging
  45.  *
  46.  * Revision 1.13 changes 08/92 by warnock@hypatia.gsfc.nasa.gov
  47.  *
  48.  *   replaced piping documents and source descriptions with curses calls
  49.  *
  50.  * Notes:
  51.  *   If there are ever more than 999 sources screen display will need
  52.  *       changes.
  53.  *
  54.  *   The use of mvprintw() is dangerous unless there is window bounds
  55.  *       checking. The curses with ULTRIX 4.2, BSD 4.3 and BSD 4.3 reno
  56.  *       have unpredictable results when the window size is exceeded.
  57.  *       Keep this in mind for further enhancements.
  58.  *
  59.  *   The ULTRIX curses.h may be missing some entries and may require
  60.  *       updating. If so, add a DEFINE ULTRIX when you compile
  61.  *
  62.  */
  63.  
  64. #include "../ir/cdialect.h"
  65. #include <curses.h>
  66. #include <signal.h>
  67. #include <setjmp.h>
  68. #include <ctype.h>
  69. #include <ui.h>
  70. #include <sockets.h>
  71. /* #include <sys/types.h> */
  72. #ifdef HAVE_NETINET_IN_H  
  73. #if BSD != 199103
  74. #include <netinet/in.h>
  75. #endif
  76. #endif
  77. #if (defined(ULTRIX) || defined(ultrix))
  78. /*
  79.  * ULTRIX 4.2 curses.h is missing these entries
  80.  */
  81. #define    erasechar()    (_tty.sg_erase)
  82. #define    killchar()    (_tty.sg_kill)
  83. #else
  84. #if (defined(__convex__))
  85. #define    erasechar()    (_tty.c_cc[VERASE])
  86. #define    killchar()    (_tty.c_cc[VKILL])
  87. #define cbreak        crmode
  88. #endif /* __convex__ */
  89. #endif /* def ULTRIX */
  90.  
  91. #define STRINGSIZE    256
  92.  
  93. #include "wais.h"
  94. #define MAIN
  95. #include "globals.h"
  96.  
  97. /*
  98. #if defined(BSD) || defined(BSD43)
  99. #include <strings.h>
  100. #define strrchr rindex
  101. #endif
  102. */
  103. #define    WAIS_SERVICE    "z39_50"
  104.  
  105. /*
  106. #define WAISSCREEN_NAME     "SWAIS"
  107. #define WAISSCREEN_VERSION  "$Revision: 1.4 $"
  108. #define WAISSCREEN_AUTHOR   "John Curran (jcurran@nnsc.nsf.net)"
  109. */
  110. #define WAISSCREEN_NAME     "SWAIS"
  111. #define WAISSCREEN_VERSION  "$Revision: 1.4 $"
  112. #define WAISSCREEN_AUTHOR   "John Curran (jcurran@nnsc.nsf.net)"
  113.  
  114. #ifndef COMMON_SOURCE_DIR
  115. #define COMMON_SOURCE_DIR "/usr/lib/wais-sources"
  116. #endif
  117.  
  118. /* SWAIS PROGRAM STATES - each decade shares common screen (0-9, 10-19, etc) */
  119. #ifndef UNKNOWN
  120. #define    UNKNOWN            0     /* curses probably already defines UNKNOWN */
  121. #endif
  122. #define    GETSOURCES    10
  123. #define    GETKEYWORDS    11
  124. #define    MAKEQUERY    12
  125. #define    SHOWRESULTS    20
  126. #define    GETOPTIONS    30
  127. #define RELDOCS        40
  128. #define    LEAVEPROGRAM    90
  129.  
  130. typedef int programstate;
  131.  
  132. /* SWAIS OPTION TYPES */
  133. #define    OPTION_BOOLEAN    0
  134. #define OPTION_INTEGER    1
  135. #define    OPTION_STRING    2
  136.  
  137. DocList Mydocs=NULL;
  138.  
  139.  
  140. typedef struct option {
  141.     char name[STRINGSIZE];
  142.     char desc[STRINGSIZE];
  143.     int type;
  144.     void (* update)();
  145.     union {
  146.         int* intptr;
  147.         char* charptr;
  148.     }
  149.     var;
  150. }
  151. _Option, *Option;
  152.  
  153. /* options */
  154. #define MAXOPTIONS 6
  155. int option_widetitles=FALSE;
  156. int option_sortsources=TRUE;
  157. int option_pagerpause=TRUE;
  158.  
  159. _Option options[MAXOPTIONS+1];
  160.  
  161. programstate state;
  162. programstate new_state;
  163. jmp_buf main_env;
  164. static char keywords[STRINGSIZE];
  165. SList Selected_Sources;
  166. char command[STRINGSIZE];
  167. char *sdir, *cdir;
  168.  
  169. #define MAXSELECTIONS 500
  170. #define NOSELECTION -999999
  171. char select_line[MAXSELECTIONS][STRINGSIZE];
  172. int selection; /* 1 to max_selection */
  173. int max_selection; /* limit on selection */
  174. int current_page; /* 0 to needed pages; preset to -1 to force refresh */
  175. int page_length; /* number of selections per page */
  176.  
  177. /* routine specific selection number */
  178. int source_selection=1;
  179. int result_selection=1;
  180. int option_selection=1;
  181. int relevant_selection = 1;
  182.  
  183. extern unsigned int sleep _AP((unsigned int seconds));
  184.  
  185. void SortSources()
  186. {
  187.     Boolean Changed = TRUE;
  188.     Source s;
  189.     SList sl;
  190.  
  191.     while(Changed) {
  192.         Changed = FALSE;
  193.         for(sl = Sources; sl->nextSource != NULL; sl = sl->nextSource) {
  194.             if(sl->nextSource->thisSource->name == NULL) {
  195.                 Changed = TRUE;
  196.                 sl->nextSource = sl->nextSource->nextSource;
  197.             }
  198.             else
  199.                 if(0 < strcasecmp(sl->thisSource->name, sl->nextSource->thisSource->name)) {
  200.                 Changed = TRUE;
  201.                 s = sl->thisSource;
  202.                 sl->thisSource = sl->nextSource->thisSource;
  203.                 sl->nextSource->thisSource = s;
  204.             }
  205.         }
  206.     }
  207. }
  208.  
  209. int freeRelDoc(dlist, number)
  210. DocList dlist;
  211. int number;
  212. {
  213.     DocList d,dm,dl;
  214.     DocList dprev=NULL;
  215.     int i;
  216.  
  217.     for(i = 0, d = dlist; (d != NULL) && (i < number); dprev=d,i++, d = d->nextDoc);
  218.  
  219.     if(dprev==NULL && d!=NULL){ /* first doc */
  220.         dl=d;
  221.         dlist=d->nextDoc;
  222.         d=dlist;
  223.         freeDocumentID(dl->thisDoc );
  224.         s_free(dl);
  225.         Mydocs=dlist;
  226.         return(listlength((List)dlist));
  227.     }
  228.     else if (d != NULL){
  229.         freeDocumentID(d->thisDoc);
  230.         dl=d;
  231.         d=dl->nextDoc;
  232.         s_free(dl);
  233.         dprev->nextDoc=d;
  234.         return(listlength((List)dlist));
  235.     }
  236.     return(0);
  237. }
  238. void screenend() {
  239.     signal(SIGINT,SIG_IGN);
  240.     clear();
  241.     refresh();
  242. /*    reset_shell_mode(); */
  243.     endwin();
  244.     echo();
  245. }
  246.  
  247. void startover() {
  248.   signal(SIGINT,startover);
  249.   longjmp(main_env,1);
  250. }
  251.  
  252. void screenstart() {
  253.     initscr();
  254.     cbreak();
  255.     noecho();
  256. /*    reset_prog_mode(); */
  257.     leaveok(stdscr,FALSE);
  258.     signal(SIGINT,startover);
  259. }
  260.  
  261. void
  262. display_context(context)
  263. char *context;
  264. {
  265.     mvprintw(LINES-3,0,context);
  266.     clrtoeol();
  267.     refresh();
  268. }
  269.  
  270. void
  271. display_prompt(prompt)
  272. char *prompt;
  273. {
  274.     mvprintw(LINES-1,0,prompt);
  275.     clrtoeol();
  276.     refresh();
  277. }
  278.  
  279. void
  280. display_highlighted(str)
  281. char *str;
  282. {
  283.     standout(); 
  284.     mvprintw(LINES-1,0,str);
  285.     standend();
  286.     printw(" ");
  287.     clrtoeol();
  288.     refresh();
  289. }
  290.  
  291. #ifdef ANSI_LIKE /* use ansi varargs */
  292. void PrintStatus(long logtype, long loglevel, char* format, ...)
  293. #else /* k&r */
  294. void PrintStatus(va_alist)
  295. va_dcl
  296. #endif /* ANSI_LIKE */
  297. {
  298.   va_list ap;            /* the variable arguments */
  299.   char message[1000];
  300.  
  301. #ifndef ANSI_LIKE
  302.   long logtype, loglevel;
  303.   char *format;
  304.  
  305.   va_start(ap);
  306.  
  307.   logtype = va_arg(ap, int);
  308.   loglevel = va_arg(ap, int);
  309.   format = va_arg(ap, char*);
  310. #else
  311.   va_start(ap, format);
  312. #endif
  313.  
  314.   vsprintf(message, format, ap);
  315.   if (stdscr!=NULL) {
  316.     display_highlighted(message);
  317.     sleep(2);
  318.   }
  319.   else
  320.     fprintf(stderr,"%s\n",message);
  321. }
  322.  
  323. char *
  324. firstphrase(str)
  325. char *str;
  326. {
  327.     char *res;
  328.     int n;
  329.  
  330.     res = str;
  331.     if ((n=strcspn(str," "))!=0)
  332.         if ((n>4) && (str[n-4]=='.')) {
  333.  
  334.             n = n - 4;
  335.             res = s_malloc(n+1);
  336.             strncpy(res,str,n);
  337.         }
  338.     return res;
  339. }
  340.  
  341. void
  342. format_option(str,opt)
  343. char *str;
  344. Option opt;
  345. {
  346.     int *p;
  347.  
  348.     switch (opt->type) { 
  349.     case OPTION_STRING:
  350.         sprintf(str,"%s", (opt->var.charptr) );
  351.         break;
  352.     case OPTION_INTEGER:
  353.         p=opt->var.intptr;
  354.         sprintf(str,"%d", *p);
  355.         break;
  356.     case OPTION_BOOLEAN:
  357.         if (* (opt->var.intptr) == TRUE)
  358.             sprintf(str,"on");
  359.         else
  360.             sprintf(str,"off");
  361.  
  362.         break;
  363.     }
  364. }
  365.  
  366. jmp_buf local_env;
  367.  
  368. char fpath[STRINGSIZE];
  369.  
  370. void
  371. start_use(fd)
  372. FILE **fd;
  373. {
  374.     *fd = fopen(fpath,"w+");
  375. }
  376.  
  377. void
  378. end_use(fd)
  379. FILE **fd;
  380. {
  381.     fclose(*fd);
  382. }
  383.  
  384. void
  385. null()
  386. {
  387. }
  388.  
  389. void
  390. Refresh_sources()
  391. {
  392.     FreeSources(Sources);
  393.     Sources = NULL;
  394.     ReadSourceDirectory(sdir,TRUE);
  395.     ReadSourceDirectory(cdir,TRUE);
  396.     if (NumSources == 0) {
  397.       PrintStatus(STATUS_URGENT, STATUS_HIGH,
  398.           "Error: Unable to find any WAIS information sources.");
  399.         exit(-1);
  400.     }
  401.     if (option_sortsources==TRUE) SortSources();
  402. }
  403.  
  404. void
  405. UseWaisDocument(q, doc)
  406. Question q;
  407. DocumentID doc;
  408. {
  409.     char message[STRINGSIZE];
  410.  
  411.     if ((doc->doc->type == NULL) || strcmp(doc->doc->type[0], "WSRC") != 0) {
  412.         fprintf(stderr, "%s", "%s is not a WAIS source.  You can only USE WAIS sources.",
  413.         firstphrase(trim_junk(doc->doc->headline)));
  414.         /* PrintStatus("%s is not a WAIS source.  You can only USE WAIS sources.",
  415.                                                         firstphrase(trim_junk(doc->doc->headline))); */
  416.     }
  417.     else {
  418.       PrintStatus(STATUS_INFO, STATUS_MEDIUM,
  419.           "Retrieving: %s\n", firstphrase(trim_junk(doc->doc->headline)));
  420.       sprintf(fpath,"%s%s.src", sdir, firstphrase(trim_junk(doc->doc->headline)));
  421.       RetrieveWaisDocument(start_use, end_use, q, doc);
  422.  
  423.       PrintStatus(STATUS_INFO, STATUS_MEDIUM,
  424.           "Adding Source: %s\n", firstphrase(trim_junk(doc->doc->headline)));
  425.       Refresh_sources();
  426.     }
  427. }
  428.  
  429.  
  430. jmp_buf local_env;
  431.  
  432. void screen_catchpipe(sig, code, scp, addr)
  433. int sig, code;
  434. struct sigcontext *scp;
  435. char *addr;
  436. {
  437.     signal(SIGPIPE,screen_catchpipe);
  438.     longjmp(local_env,1);
  439. }
  440.  
  441. char pipe_cmd[STRINGSIZE];
  442.  
  443. void
  444. start_pipe(pipefd)
  445. FILE **pipefd;
  446. {
  447.     screenend();
  448.     *pipefd = popen(pipe_cmd,"w");
  449. }
  450.  
  451. void
  452. end_pipe(pipefd)
  453. FILE **pipefd;
  454. {
  455.     pclose(*pipefd);
  456. }
  457.  
  458. void AddDocAsRelevant(doc)
  459. DocumentID doc;
  460. {
  461.     int i;
  462.     char bf[10];
  463.  
  464.     Mydocs=makeDocList(doc,Mydocs);
  465. }
  466.  
  467. void
  468. PipeWaisDocument(q, doc, cmd)
  469. Question q;
  470. DocumentID doc;
  471. char *cmd;
  472. {
  473.     char message[STRINGSIZE];
  474.  
  475.     PrintStatus(STATUS_INFO, STATUS_MEDIUM,
  476.         "Retrieving: %s\n",firstphrase(trim_junk(doc->doc->headline)));
  477.  
  478.     strcpy(pipe_cmd,cmd);
  479.     signal(SIGPIPE,screen_catchpipe);
  480.     if (setjmp(local_env)==0) RetrieveWaisDocument(start_pipe,end_pipe,q,doc); 
  481.     signal(SIGPIPE,SIG_DFL);
  482. }
  483.  
  484.   void
  485. DisplayWaisDocument(q, doc)
  486. Question q;
  487. DocumentID doc;
  488. {
  489.     char message[STRINGSIZE];
  490.  
  491.     PrintStatus(STATUS_INFO, STATUS_MEDIUM,
  492.         "Retrieving: %s\n",firstphrase(trim_junk(doc->doc->headline)));
  493.  
  494.     RetrieveWaisDocument(NULL,NULL,q,doc); 
  495. }
  496.  
  497. void
  498. FreeSourceList(sources)
  499. SourceList sources;
  500. {
  501.     SourceList s, n;
  502.  
  503.     for (s = sources; s != NULL; s = n) {
  504.         if (s->thisSource != NULL) {
  505.             if (s->thisSource->filename != NULL)
  506.                 s_free(s->thisSource->filename);
  507.             s_free(s->thisSource);
  508.         }
  509.  
  510.         n = s->nextSource;
  511.         s_free(s);
  512.     }
  513. }
  514.  
  515. void AddQuestionSource(question, sourcename)
  516. Question question;
  517. char *sourcename;
  518. {
  519.     SourceList tmp;
  520.     SourceList s;
  521.     SourceID sid;
  522.  
  523.     sid = (SourceID)s_malloc(sizeof(_SourceID));
  524.     sid->filename = s_strdup(sourcename);
  525.     s = (SourceList)s_malloc(sizeof(_SourceList));
  526.     s->thisSource = sid;
  527.     s->nextSource = NULL;
  528.     tmp = question->Sources;
  529.     question->Sources = s;
  530.     if (tmp != NULL) 
  531.         s->nextSource = tmp;
  532. }
  533.  
  534. void
  535. usage(name)
  536. char *name;
  537. {
  538.     fprintf(stderr,"Usage: %s\n",name);
  539.     fprintf(stderr,"  [-s sourcname]          select sourcename for search\n");
  540.     fprintf(stderr,"  [-S sourcedir]          defaults to ~/wais-sources\n");
  541.     fprintf(stderr,"  [-C common_sourcedir]   defaults to %s\n",COMMON_SOURCE_DIR);
  542.     fprintf(stderr,"  [-h]                  this help message\n");
  543.     fprintf(stderr,"  [keywords]\n");
  544. }
  545.  
  546.  
  547. SourceID FindQuestionSource(sourcelist, sourcename) 
  548. SourceList sourcelist;
  549. char *sourcename;
  550. {
  551.     SourceList tmpsource;
  552.     for(tmpsource = sourcelist; tmpsource != NULL; 
  553.  tmpsource = tmpsource->nextSource) {
  554.             if (tmpsource->thisSource != NULL)
  555.             if (!strcmp(sourcename, tmpsource->thisSource->filename)) 
  556.                 return(tmpsource->thisSource);
  557.     }
  558.     return(NULL);
  559. }
  560.  
  561. Source FindSource(sourcelist, sourcename) 
  562. SList sourcelist;
  563. char *sourcename;
  564. {
  565.     SList tmpsource;
  566.     for(tmpsource = sourcelist; tmpsource != NULL; 
  567.  tmpsource = tmpsource->nextSource) {
  568.             if (tmpsource->thisSource != NULL)
  569.             if (!strcmp(sourcename, tmpsource->thisSource->name)) 
  570.                 return(tmpsource->thisSource);
  571.     }
  572.     return(NULL);
  573. }
  574.  
  575. void
  576. DumpSources(sourcelist)
  577. SList sourcelist;
  578. {
  579.     SList tmpsource;
  580.  
  581.     if (sourcelist == NULL) {
  582.         printf("Sourcelist NULL");
  583.         return;
  584.     }
  585.  
  586.     printf(" Dump of Sourcelist \n");
  587.     for(tmpsource = sourcelist; tmpsource != NULL; tmpsource = tmpsource->nextSource) {
  588.         if (tmpsource->thisSource == NULL) 
  589.             printf("    thisSource NULL\n");
  590.         else
  591.             printf("    thisSource = %s\n",tmpsource->thisSource->name);
  592.         if (tmpsource->nextSource == NULL) 
  593.             printf("    nextSource NULL\n");
  594.         else
  595.             printf("    following nextSource ->\n");
  596.     }
  597. }
  598.  
  599.  
  600. SList
  601. AddSource(sourcelist,currentsource)
  602. SList sourcelist;
  603. Source currentsource;
  604. {
  605.     Source s;
  606.     SList tmpsource;
  607.     SList last;
  608.  
  609.     if (sourcelist == NULL)
  610.         sourcelist = makeSList(NULL,NULL);
  611.  
  612.     last=sourcelist;
  613.  
  614.     for(tmpsource = sourcelist; tmpsource != NULL; 
  615.  last = tmpsource, tmpsource = tmpsource->nextSource) 
  616.             if (tmpsource->thisSource != NULL)
  617.             if (!strcmp(currentsource->name, tmpsource->thisSource->name)) 
  618.                 return(sourcelist);
  619.  
  620.     s = (Source) s_malloc(sizeof(_Source));
  621.     s->initp = currentsource->initp;
  622.     s->name = s_strdup(currentsource->name);
  623.     s->directory = s_strdup(currentsource->directory);
  624.  
  625.     if (last->thisSource == NULL) 
  626.         last->thisSource = s;
  627.     else
  628.         last->nextSource = makeSList(s, NULL); 
  629.     return(sourcelist);
  630. }
  631.  
  632. SList
  633. DeleteSource(sourcelist,currentsource)
  634. SList sourcelist;
  635. Source currentsource;
  636. {
  637.     SList s;
  638.     SList tmpsource;
  639.     SList last;
  640.  
  641.     if (sourcelist == NULL)
  642.         return(NULL);
  643.  
  644.     last=sourcelist;
  645.  
  646.     for(tmpsource = sourcelist; tmpsource != NULL; 
  647.  last = tmpsource, tmpsource = tmpsource->nextSource) 
  648.             if (tmpsource->thisSource != NULL)
  649.             if (!strcmp(currentsource->name, tmpsource->thisSource->name)) {
  650.                 if(tmpsource->thisSource->name != NULL)
  651.                     s_free (tmpsource->thisSource->name);
  652.                 if(tmpsource->thisSource->directory != NULL)
  653.                     s_free (tmpsource->thisSource->directory);
  654.                 if(tmpsource->thisSource->maintainer != NULL)
  655.                     s_free (tmpsource->thisSource->maintainer);
  656.  
  657.                 /* save next link ptr, discard current link */
  658.                 s = tmpsource->nextSource; 
  659.                 s_free (tmpsource);
  660.  
  661.                 /* return next as start if start destroyed */
  662.                 if (last==sourcelist)
  663.                     return(s);
  664.  
  665.                 /* Splice next into position, return start ptr */
  666.                 last->nextSource = s;
  667.                 break;
  668.             }
  669.     return(sourcelist);
  670. }
  671.  
  672. char *
  673. fixdirname(dir)
  674. char *dir;
  675. {
  676.     char *res;
  677.  
  678.     if(dir[strlen(dir)-1] == '/') res = dir;
  679.     else {
  680.         res = s_malloc(strlen(dir)+2);
  681.         sprintf(res,"%s/", dir);
  682.     }
  683.     return res;
  684. }
  685.  
  686. int
  687. selection_page(sel)
  688. int sel;
  689. {
  690.     return(((sel-1) /page_length));
  691. }
  692.  
  693. int
  694. selection_line(sel)
  695. int sel;
  696. {
  697.     return(((sel-1) % page_length)+2);
  698. }
  699.  
  700. selection_display(new_sel)
  701. int new_sel;
  702. {
  703.     int new_page;
  704.     int new_selection;
  705.     int sel_offset;
  706.     int k;
  707.  
  708.     standend();
  709.     mvprintw(selection_line(selection),0,"%s",select_line[selection]);
  710.  
  711.     if (new_sel==NOSELECTION) 
  712.         new_selection = selection;
  713.     else
  714.         new_selection = new_sel;
  715.  
  716.     if (new_selection < 1)
  717.         new_selection = max_selection;
  718.     if (new_selection > max_selection) 
  719.         new_selection = 1;
  720.  
  721.     new_page = selection_page(new_selection);
  722.     if (current_page!=new_page) {
  723.         sel_offset = new_page * page_length;
  724.         for (k = 1; k <= page_length; k++) 
  725.             if ((sel_offset+k)<=max_selection)
  726.                 mvprintw(1+k,0,"%s",select_line[sel_offset+k]);
  727.         else
  728.             mvprintw(1+k,0,"\n");
  729.     }
  730.  
  731.     if (new_sel!=NOSELECTION) {
  732.         standout();
  733.         mvprintw(selection_line(new_selection),0,"%s",select_line[new_selection]);
  734.         standend();
  735.     }
  736.     move(selection_line(new_selection),0);
  737.     current_page = new_page;
  738.     selection = new_selection;
  739.     refresh();
  740. }
  741.  
  742. void
  743. title_display(title,status,status_count)
  744. char *title;
  745. char *status;
  746. int status_count;
  747. {
  748.     mvprintw(0,0,WAISSCREEN_NAME);
  749.     standout();
  750.     mvprintw(0,COLS/2-(strlen(title)/2),"%s", title);
  751.     standend();
  752.     mvprintw(0,COLS-(strlen(status)+4),"%s %2ld", status, status_count);
  753. }
  754.  
  755. void DumpTextToScreen(buffer, size)
  756.      char *buffer;
  757.      long size;
  758. {
  759.   int  linecnt, j, i;
  760.   char ch;
  761.   int  OUTLINES;
  762.  
  763.   OUTLINES = LINES - 1;
  764.   clear();
  765.   title_display("Document Display", "Page:", 1);
  766.   move(1,0);
  767.   linecnt = 1;
  768.  
  769.   for (i = 0; i < size; i++, j++)
  770.     {
  771.     addch(buffer[i]);
  772.  
  773.     if (buffer[i] < ' ')
  774.       {
  775.         clrtoeol();
  776.         refresh();
  777.         linecnt++;
  778.       }
  779.  
  780.     if (linecnt == OUTLINES - 1)
  781.       {
  782.         PrintStatus(STATUS_URGENT, STATUS_HIGH,
  783.             "Press any key to continue, 'q' to quit.");
  784.         ch = getch();
  785.         if ((ch == 'q') || (ch == 'Q')) {
  786.           return;
  787.         } else {
  788.           clear();
  789.           move(0,0);
  790.           linecnt = 0;
  791.         }
  792.       }
  793.       }
  794.   PrintStatus(STATUS_URGENT, STATUS_HIGH, "Press a key to continue");
  795.   getch();
  796. }
  797.  
  798. void
  799. show_source_entry_help()
  800. {
  801.     int j=2;
  802.  
  803.     clear();
  804.     title_display("Source Selection Help","Page:",1);
  805.     mvprintw(j++,0,"%s\t%s","j, down arrow, ^N","Move Down one source");
  806.     mvprintw(j++,0,"%s\t%s","k, up arrow, ^P  ","Move Up one source");
  807.     mvprintw(j++,0,"%s\t%s","J, ^V, ^D        ","Move Down one screen");
  808.     mvprintw(j++,0,"%s\t%s","K, <esc> v, ^U   ","Move Up one screen");
  809.     mvprintw(j++,0,"%s\t%s","###              ","Position to source number ##");
  810.     mvprintw(j++,0,"%s\t%s","/sss             ","Search for source sss");
  811.     mvprintw(j++,0,"%s\t%s","<space>, <period>","Select current source");
  812.     mvprintw(j++,0,"%s\t%s","=                ","Deselect all sources");
  813.     mvprintw(j++,0,"%s\t%s","v, <comma>       ","View current source info");
  814.     mvprintw(j++,0,"%s\t%s","<ret>            ","Perform search");
  815.     mvprintw(j++,0,"%s\t%s","s                ","Select new sources (refresh sources list)");
  816.     mvprintw(j++,0,"%s\t%s","w                ","Select new keywords");
  817.     mvprintw(j++,0,"%s\t%s","X, -             ","Remove current source permanently");
  818.     mvprintw(j++,0,"%s\t%s","o                ","Set and show swais options");
  819.     mvprintw(j++,0,"%s\t%s","h, ?             ","Show this help display");
  820.     mvprintw(j++,0,"%s\t%s","H                ","Display program history");
  821.     mvprintw(j++,0,"%s\t%s","q                ","Leave this program");
  822.     PrintStatus(STATUS_URGENT, STATUS_HIGH,
  823.         "Press any key to continue"); 
  824.     getch();
  825. }
  826.  
  827. void
  828. view_source_info(sourcelist,current_s)
  829. SList sourcelist;
  830. Source current_s;
  831. {
  832.     FILE *fp;
  833.     int j=2;
  834.     char tmp_str[STRINGSIZE];
  835.  
  836.     clear();
  837.     title_display("Source Info", "Page:", 1);
  838.     if (NULL != current_s->name) 
  839.         mvprintw(j++,0,"%s\t%s","Name:       ",current_s->name);
  840.     if (NULL != current_s->directory) 
  841.         mvprintw(j++,0,"%s\t%s","Directory:  ",current_s->directory);
  842.     if (NULL != current_s->maintainer) 
  843.         mvprintw(j++,0,"%s\t%s","Maintainer: ",current_s->maintainer);
  844.     if (NULL != FindSource(sourcelist,current_s->name)) 
  845.         sprintf(tmp_str,"Yes");
  846.     else
  847.         sprintf(tmp_str,"No");
  848.     mvprintw(j++,0,"%s\t%s","Selected:   ",tmp_str);
  849.     format_source_cost(tmp_str,current_s);
  850.     mvprintw(j++,0,"%s\t%s","Cost:       ",tmp_str);
  851.     if (current_s->initp) 
  852.         sprintf(tmp_str,"(Accessed)");
  853.     else
  854.         tmp_str[0]='\0';
  855.     if (NULL != current_s->server) 
  856.         mvprintw(j++,0,"%s\t%s %s","Server:     ",current_s->server,tmp_str);
  857.     if (NULL != current_s->service) 
  858.         mvprintw(j++,0,"%s\t%s","Service:    ",current_s->service);
  859.     if (NULL != current_s->database) 
  860.         mvprintw(j++,0,"%s\t%s","Database:   ",current_s->database);
  861.     if (NULL != current_s->description) {
  862.       mvprintw(j++,0,"%s","Description:");
  863.       mvprintw(j++,0,"%s",current_s->description);
  864.     }
  865.  
  866.     clearok(stdscr,FALSE);
  867.     PrintStatus(STATUS_URGENT, STATUS_HIGH, "Press any key to continue.");
  868.     cbreak();
  869.     noecho();
  870.     getch();
  871. }
  872.  
  873. void
  874. view_result_info(current_doc)
  875. DocumentID current_doc;
  876. {
  877.     int j=2;
  878.     char tmp_str[STRINGSIZE];
  879.  
  880.     clear();
  881.     title_display("Result Information","Page:",1);
  882.  
  883.     /*  sure.. someday these might have data. jtc
  884.                             GetServer(current_doc->doc->id,tmp_str);
  885.                             mvprintw(j++,0,"%s\t%s","Server:     ",tmp_str);
  886.                             GetDatabase(current_doc->doc->id,tmp_str);
  887.                             mvprintw(j++,0,"%s\t%s","Database:   ",tmp_str);
  888.                             GetLocalID(current_doc->doc->id,tmp_str);
  889.                             mvprintw(j++,0,"%s\t%s","Local ID:   ",tmp_str);
  890.                         */
  891.     if (NULL != current_doc->doc->date) 
  892.         mvprintw(j++,0,"%s\t%s","Date:       ",current_doc->doc->date);
  893.     if (NULL != current_doc->doc->headline) 
  894.         mvprintw(j++,0,"%s\t%s","Source:     ",current_doc->doc->source);
  895.     if (NULL != current_doc->doc->headline) 
  896.         mvprintw(j++,0,"%s\t%s","Headline:   ",current_doc->doc->headline);
  897.     if (NULL != current_doc->doc->city) 
  898.         mvprintw(j++,0,"%s\t%s","City:       ",current_doc->doc->city);
  899.     if (NULL != current_doc->doc->stock) 
  900.         mvprintw(j++,0,"%s\t%s","Stock:      ",current_doc->doc->stock);
  901.     if (NULL != current_doc->doc->company) 
  902.         mvprintw(j++,0,"%s\t%s","Company:    ",current_doc->doc->company);
  903.     if (NULL != current_doc->doc->industry) 
  904.         mvprintw(j++,0,"%s\t%s","Industry:   ",current_doc->doc->industry);
  905.     if ((NULL != current_doc->doc->type) && current_doc->doc->type[0] != NULL)
  906.         mvprintw(j++,0,"%s\t%s","Type:       ",current_doc->doc->type[0]);
  907.     mvprintw(j++,0,"%s\t%d","Score       ",current_doc->rawScore);
  908.  
  909.     mvprintw(j++,0,"%s\t%ld","# of Lines: ",current_doc->doc->numLines);
  910.     mvprintw(j++,0,"%s\t%ld","# of Chars: ",current_doc->doc->numChars);
  911.  
  912.     if (NULL != current_doc->doc->sourceID->filename) 
  913.         mvprintw(j++,0,"%s\t%s","SourceID:   ",current_doc->doc->sourceID->filename);
  914.     switch (GetCopyrightDisposition(current_doc->doc->id)) {
  915.  
  916.         case (COPY_WITHOUT_RESTRICTION) :
  917.         sprintf(tmp_str,"Copy Without Restriction");
  918.         break;
  919.         case (ALL_RIGHTS_RESERVED) :
  920.         sprintf(tmp_str,"All Rights Reserved");
  921.         break;
  922.         case (DISTRIBUTION_RESTRICTIONS_APPLY) :
  923.         sprintf(tmp_str,"Distribution Restrictions Apply");
  924.         break;
  925.     default :
  926.         sprintf(tmp_str,"Unknown");
  927.         break;
  928.     }
  929.     mvprintw(j++,0,"%s\t%s","Disposition: ",tmp_str);
  930.  
  931.     PrintStatus(STATUS_URGENT, STATUS_HIGH,
  932.         "Press any key to continue"); 
  933.     getch();
  934. }
  935.  
  936. void
  937. show_swais_history()
  938. {
  939.     char versiononly[STRINGSIZE];
  940.     int j=2;
  941.  
  942.     clear();
  943.     title_display("SWAIS History","Page:",1);
  944.     mvprintw(j++,0,"%s"," ");
  945.     mvprintw(j++,0,"%s",
  946.     "The WAIS (Wide Area Information Service) system is a collection of programs");
  947.     mvprintw(j++,0,"%s",
  948.     "which provide for convenient information distribution over wide area networks.");
  949.     mvprintw(j++,0,"%s",
  950.     "Tools for both \"publishing\" and accessing information sources are provided.");
  951.     mvprintw(j++,0,"%s",
  952.     "The Simple WAIS (SWAIS) interface is an basic access tool designed for those");
  953.     mvprintw(j++,0,"%s",
  954.     "focused on data retreival and not computer operation. It provides most of the");
  955.     mvprintw(j++,0,"%s",
  956.     "functionality of the more complicated interfaces but features a simple and");
  957.     mvprintw(j++,0,"%s",
  958.     "potentially more natural interface.  The functionality supported includes ");
  959.     mvprintw(j++,0,"%s",
  960.     "source selection, keyword entry, and automatic document retrieval.");
  961.     mvprintw(j++,0,"%s",
  962.     "I hope that this tool may be of use.  Enjoy.");
  963.     mvprintw(j++,0,"%s"," ");
  964.     mvprintw(j++,0,"%s",
  965.     "The WAIS system is the result of a joint project between Thinking Machines,");
  966.     mvprintw(j++,0,"%s",
  967.     "Apple Computer, and Dow Jones.  For more information on WAIS, send mail to");
  968.     mvprintw(j++,0,"%s",
  969.     "\"wais-discussion@think.com\".  The current release of the WAIS software");
  970.     mvprintw(j++,0,"%s",
  971.     "is available via anonymous ftp from think.com in subdirectory wais.");
  972.     sscanf(WAISSCREEN_VERSION,"$ %*s %s",versiononly);
  973.     mvprintw(LINES-5,0,"Simple Wais %s [built with %s]", versiononly,VERSION);
  974.     mvprintw(LINES-3,0,"%s", WAISSCREEN_AUTHOR);
  975.  
  976.     PrintStatus(STATUS_URGENT, STATUS_HIGH, "Press any key to continue"); 
  977.     getch();
  978. }
  979.  
  980. void
  981. show_relevant_help()
  982. {
  983.     int j=2;
  984.  
  985.     clear();
  986.     title_display("Relevant Doc. Help","Page:",1);
  987.     mvprintw(j++,0,"%s\t\t%s","j, ^N  ","Move Down one item");
  988.     mvprintw(j++,0,"%s\t\t%s","k, ^P  ","Move Up one item");
  989.     mvprintw(j++,0,"%s\t\t%s","J      ","Move Down one screen");
  990.     mvprintw(j++,0,"%s\t\t%s","K      ","Move Up one screen");
  991.     mvprintw(j++,0,"%s\t\t%s","D      ","Delete All Relevant Docs");
  992.     mvprintw(j++,0,"%s\t\t%s","X      ","Delete Current Relevant Doc");
  993.     mvprintw(j++,0,"%s\t\t%s","<space>","Display current item");
  994.     mvprintw(j++,0,"%s\t\t%s","<return>","Display current item");
  995.     mvprintw(j++,0,"%s\t\t%s","v      ","View current item information");
  996.  
  997.     PrintStatus(STATUS_URGENT, STATUS_HIGH,"Press any key to continue");
  998.     getch();
  999. }
  1000.  
  1001. void
  1002. show_search_results_help()
  1003. {
  1004.     int j=2;
  1005.  
  1006.     clear();
  1007.     title_display("Search Results Help","Page:",1);
  1008.     mvprintw(j++,0,"%s\t\t%s","j, ^N  ","Move Down one item");
  1009.     mvprintw(j++,0,"%s\t\t%s","k, ^P  ","Move Up one item");
  1010.     mvprintw(j++,0,"%s\t\t%s","J      ","Move Down one screen");
  1011.     mvprintw(j++,0,"%s\t\t%s","K      ","Move Up one screen");
  1012.     mvprintw(j++,0,"%s\t\t%s","R      ","Show relevant documents");
  1013.     mvprintw(j++,0,"%s\t\t%s","S      ","Save current item to a file");
  1014.     mvprintw(j++,0,"%s\t\t%s","m      ","Mail current item to an address");
  1015.     mvprintw(j++,0,"%s\t\t%s","##     ","Position to item number ##");
  1016.     mvprintw(j++,0,"%s\t\t%s","/sss   ","Position to item beginning sss");
  1017.     mvprintw(j++,0,"%s\t\t%s","<space>","Display current item");
  1018.     mvprintw(j++,0,"%s\t\t%s","<return>","Display current item");
  1019. #ifndef SECURECLIENT
  1020.     mvprintw(j++,0,"%s\t\t%s","|      ","Pipe current item into a unix command");
  1021. #endif
  1022.     mvprintw(j++,0,"%s\t\t%s","v      ","View current item information");
  1023.     mvprintw(j++,0,"%s\t\t%s","r      ","Make current item a relevant document");
  1024.     mvprintw(j++,0,"%s\t\t%s","s      ","Specify new sources to search");
  1025.     mvprintw(j++,0,"%s\t\t%s","u      ","Use it; add it to the list of sources");
  1026.     mvprintw(j++,0,"%s\t\t%s","w      ","Make another search with new keywords");
  1027.     mvprintw(j++,0,"%s\t\t%s","o      ","Set and show swais options");
  1028.     mvprintw(j++,0,"%s\t\t%s","h      ","Show this help display");
  1029.     mvprintw(j++,0,"%s\t\t%s","H      ","Display program history");
  1030.     mvprintw(j++,0,"%s\t\t%s","q      ","Leave this program");
  1031.     PrintStatus(STATUS_URGENT, STATUS_HIGH, "Press any key to continue"); 
  1032.     getch();
  1033. }
  1034.  
  1035. int
  1036. get_input_string(str)
  1037. char str[STRINGSIZE];
  1038. {
  1039.     int startcol, startline;
  1040.     int pos;
  1041.     char ch;
  1042.  
  1043.     getyx(stdscr, startline, startcol);
  1044.     addstr(str);
  1045.     clrtoeol();
  1046.     refresh();
  1047.  
  1048.     pos = strlen(str);
  1049.     while(TRUE) {
  1050.  
  1051.         ch=getch();
  1052.         if (ch==killchar()) {
  1053.             move(startline, startcol);
  1054.             clrtoeol();
  1055.             refresh();
  1056.             str[0] = 0;
  1057.             pos = 0;
  1058.         }
  1059.         else
  1060.             if ((ch==erasechar())||(ch==127)) {
  1061.                 if (pos>0) {
  1062.                     str[--pos]='\0';
  1063.                     mvaddch(startline,startcol+pos,' ');
  1064.                     move(startline,startcol+pos);
  1065.                     refresh();
  1066.                 }
  1067.                 else {
  1068.                     str[0]='\0';
  1069.                     break;
  1070.                 }
  1071.             }
  1072.         else
  1073.             if (ch=='\n')
  1074.             break;
  1075.         else 
  1076.             if (isprint(ch)){
  1077.                 str[pos++]=ch;
  1078.                 str[pos]='\0';
  1079.                 addch(ch);
  1080.                 refresh();
  1081.             }
  1082.  
  1083.     }
  1084.  
  1085.     display_prompt("");
  1086.     return(str[0]!='\0');
  1087. }
  1088.  
  1089. void
  1090. display_source_selected(sourcelist,currentsource)
  1091. SList sourcelist;
  1092. Source currentsource;
  1093. {
  1094.     if (NULL != FindSource(sourcelist,currentsource->name)) {
  1095.         mvprintw(selection_line(selection),5,"*");
  1096.     }
  1097.     else {
  1098.         mvprintw(selection_line(selection),5," ");
  1099.     }
  1100. }
  1101.  
  1102. void
  1103. source_selected(sourcelist,currentsource,sel)
  1104. SList sourcelist;
  1105. Source currentsource;
  1106. {
  1107.     if (NULL != FindSource(sourcelist,currentsource->name)) {
  1108.         select_line[sel][5] = '*';
  1109.     }
  1110.     else {
  1111.         select_line[sel][5] = ' ';
  1112.     }
  1113. }
  1114.  
  1115. programstate
  1116. nextstate(question)
  1117. Question question;
  1118. {
  1119.     if ((question->numsources==0) || !(question->modified)) {
  1120.         return(GETSOURCES);
  1121.     }
  1122.  
  1123.     return(GETKEYWORDS);
  1124. }
  1125.  
  1126. programstate
  1127. makequery_state(question)
  1128. Question question;
  1129. {
  1130.     SList asource;
  1131.  
  1132.     /* rebuild question source list from Selected_Sources */
  1133.     FreeSourceList(question->Sources);
  1134.     question->Sources = NULL;
  1135.     /* build new question source list */
  1136.     for (asource = Selected_Sources; 
  1137.  asource != NULL ; asource = asource->nextSource)
  1138.             if (asource->thisSource != NULL) 
  1139.             AddQuestionSource(question,asource->thisSource->name);
  1140.     question->numsources = listlength((List)question->Sources);
  1141.  
  1142.     question->RelevantDocuments = Mydocs;
  1143.     question->numdocs = listlength((List)question->RelevantDocuments);
  1144.     question->ResultDocuments = NULL;
  1145.     question->numresdocs = listlength((List)question->ResultDocuments);
  1146.     question->maxresdocs = *options[6].var.intptr;
  1147.  
  1148.     SearchWais(question);
  1149.     question->modified = FALSE;
  1150.  
  1151.     if(question->numresdocs > 0) {
  1152.         result_selection = 1;
  1153.         return(SHOWRESULTS);
  1154.     }
  1155.     else 
  1156.         return(nextstate(question));
  1157. }
  1158.  
  1159. void
  1160. option_screen(question)
  1161. Question question;
  1162. {
  1163.     DocList doclist;
  1164.     DocumentID current_doc;
  1165.     int k;
  1166.     int option_count;
  1167.     char fstr[STRINGSIZE];
  1168.     char tstr[STRINGSIZE];
  1169.     char *sourcename;
  1170.  
  1171.     option_count = MAXOPTIONS;
  1172.  
  1173.     title_display("Option Settings","Options:", option_count);
  1174.  
  1175.     mvprintw(1,2,"#    Option        Value ");
  1176.     sprintf(fstr,"%%03d:   %%-12.12s  %%-%d.%ds",COLS-22,COLS-22);
  1177.  
  1178.     for (k=1; k <= option_count; k++) {
  1179.         format_option(tstr,&options[k]);
  1180.         sprintf(select_line[k], fstr, k, options[k].name, tstr);
  1181.     }
  1182.  
  1183.     selection = option_selection;
  1184.     current_page = -1;
  1185.     max_selection= option_count;
  1186.     page_length= MINIMUM(LINES-6, option_count);
  1187.     selection_display(NOSELECTION);
  1188.  
  1189. }
  1190.  
  1191. programstate
  1192. option_state(question)
  1193. Question question;
  1194. {
  1195.  
  1196.     char user_key[STRINGSIZE];
  1197.     char digit_str[STRINGSIZE];
  1198.     int k,miss, option_count;
  1199.  
  1200.     option_count = MAXOPTIONS+1;
  1201.     selection_display(selection);
  1202.     display_context(options[selection].desc);
  1203.  
  1204.     digit_str[0]='\0';
  1205.     while(TRUE) {
  1206.         display_prompt("<space> to change, arrows to move, s for sources, r for results, ? for help");
  1207.         user_key[0]=getch();
  1208.         switch(user_key[0]) {
  1209.  
  1210.         case 'h' :
  1211.             ;
  1212.         case '?' :
  1213.             show_search_results_help();
  1214.             state=UNKNOWN;
  1215.             return(GETOPTIONS);
  1216.  
  1217.             /* forgive me: hardwired arrow keys for vt100 since we're
  1218.                                                                              not using SysV curses and bsd curses lacks key support  */
  1219.         case '\033' :
  1220.             user_key[1]=getch();
  1221.             user_key[2]=getch();
  1222.             user_key[3]='\0';
  1223.         if ((strcmp(user_key, "\033[A") == 0) ||
  1224.         (strcmp(user_key, "\033OA") == 0)) {
  1225.                 selection_display(selection-1);
  1226.                 display_context(options[selection].desc);
  1227.                 option_selection = selection;
  1228.                 break;
  1229.             }
  1230.         if ((strcmp(user_key, "\033[B") == 0) ||
  1231.         (strcmp(user_key, "\033OB") == 0)) {
  1232.                 selection_display(selection+1);
  1233.                 display_context(options[selection].desc);
  1234.                 option_selection = selection;
  1235.                 break;
  1236.             }
  1237.  
  1238.             /* emacs <meta>v or left arrow = page previous */
  1239.         if (user_key[1]=='v' ||
  1240.         (strcmp(user_key, "\033[D") == 0) ||
  1241.         (strcmp(user_key, "\033OD") == 0)) {
  1242.                 selection_display(selection-page_length);
  1243.                 display_context(options[selection].desc);
  1244.                 option_selection = selection;
  1245.                 break;
  1246.             }
  1247.  
  1248.         /* right arrow = page next */
  1249.         if ((strcmp(user_key, "\033[C") == 0) ||
  1250.         (strcmp(user_key, "\033OC") == 0)) {
  1251.           selection_display(selection+page_length);
  1252.           display_context(options[selection].desc);
  1253.           option_selection = selection;
  1254.           break;
  1255.         }
  1256.  
  1257.             break;
  1258.  
  1259.         case 10 :
  1260.             ;
  1261.         case ' ' :
  1262.             k = selection;
  1263.             switch (options[k].type) {
  1264.             case OPTION_INTEGER :
  1265.                 digit_str[0]='\0';
  1266.                 mvprintw(LINES-3,0,"New Value: ");
  1267.                 get_input_string(digit_str);
  1268.                 if (atoi(digit_str)!= 0) {
  1269.                     *(options[k].var.intptr) = atoi(digit_str);
  1270.                     options[k].update();
  1271.                 }
  1272.                 standend();
  1273.                 mvprintw(LINES-3,0," ");
  1274.                 clrtoeol();
  1275.                 break;
  1276.             case OPTION_STRING :
  1277.                 digit_str[0]='\0';
  1278.                 mvprintw(LINES-3,0,"New Value: ");
  1279.                 if (get_input_string(digit_str)){
  1280.                     strcpy(options[k].var.charptr, digit_str);
  1281.                     options[k].update();
  1282.                 }
  1283.                 standend();
  1284.                 mvprintw(LINES-3,0," ");
  1285.                 clrtoeol();
  1286.                 break;
  1287.             case OPTION_BOOLEAN :
  1288.                 if (* (options[k].var.intptr) == TRUE)
  1289.                     *(options[k].var.intptr) = FALSE;
  1290.                 else
  1291.                     *(options[k].var.intptr) = TRUE;
  1292.                 options[k].update();
  1293.                 break;
  1294.             }
  1295.             state=UNKNOWN;
  1296.             return(GETOPTIONS);
  1297.  
  1298.         case 14 :
  1299.             ;
  1300.         case 'j' :
  1301.             selection_display(selection+1); 
  1302.             display_context(options[selection].desc);
  1303.             option_selection = selection;
  1304.             break;
  1305.  
  1306.         case 16 :
  1307.             ;
  1308.         case 'k' :
  1309.             selection_display(selection-1); 
  1310.             display_context(options[selection].desc);
  1311.             option_selection = selection;
  1312.             break;
  1313.  
  1314.         case 'q' :
  1315.             return(LEAVEPROGRAM);
  1316.         case 's' :
  1317.             return(GETSOURCES);
  1318.         case 'r' :
  1319.             if(question->numresdocs > 0) return(SHOWRESULTS);
  1320.             break;
  1321.         case 'w' :
  1322.             return(GETKEYWORDS);
  1323.  
  1324.         case 18 :
  1325.             ;
  1326.         case '\f' :
  1327.             wrefresh(curscr);
  1328.             break;
  1329.  
  1330.         case '/' :
  1331.             user_key[0] = '\0';
  1332.             mvprintw(LINES-3,0,"Option Name: ");
  1333.             get_input_string(user_key);
  1334.             standend();
  1335.             mvprintw(LINES-3,0," ");
  1336.             clrtoeol();
  1337.             refresh();
  1338.             if (strlen(user_key)) {
  1339.                 miss = TRUE;
  1340.                 for (k=1 ; k <= option_count ; k++ ) {
  1341.                     if (!strncasecmp(user_key,options[k].name,
  1342.                     strlen(user_key))) {
  1343.                         selection_display(k);
  1344.                         option_selection = k;
  1345.                         miss = FALSE;
  1346.                         break;
  1347.                     }
  1348.                 }
  1349.                 if (miss=TRUE) 
  1350.           PrintStatus(STATUS_URGENT, STATUS_HIGH,
  1351.                   "Unable to find item");
  1352.             }
  1353.             display_context(options[option_selection].desc);
  1354.             break;
  1355.  
  1356.         case 4 :
  1357.             ;
  1358.         case 22 :
  1359.             ; /* emacs ctrl-v */
  1360.         case 'J' :
  1361.             selection_display(selection+page_length);
  1362.             display_context(options[selection].desc);
  1363.             option_selection = selection;
  1364.             break;
  1365.  
  1366.         case 21 :
  1367.             ;
  1368.         case 'K' :
  1369.             selection_display(selection-page_length); 
  1370.             display_context(options[selection].desc);
  1371.             option_selection = selection;
  1372.             break;
  1373.  
  1374.         default :
  1375.             if (isdigit(user_key[0])) {
  1376.                 digit_str[0] = user_key[0];
  1377.                 digit_str[1] = '\0';
  1378.                 mvprintw(LINES-3,0,"Item Number: ");
  1379.                 get_input_string(digit_str);
  1380.                 if (atoi(digit_str)!= 0) {
  1381.                     selection_display(atoi(digit_str));
  1382.                     option_selection = selection;
  1383.                 }
  1384.                 standend();
  1385.                 mvprintw(LINES-3,0," ");
  1386.                 clrtoeol();
  1387.                 display_context(options[selection].desc);
  1388.             }
  1389.         }
  1390.     }
  1391. }
  1392.  
  1393. void
  1394. source_screen(question)
  1395. Question question;
  1396. {
  1397.     int k;
  1398.     int source_count;
  1399.     Source current_s;
  1400.     SList asource;
  1401.     char fstr[STRINGSIZE];
  1402.  
  1403.     source_count = listlength((List)Sources);
  1404.  
  1405.     title_display("Source Selection","Sources:",source_count);
  1406.     mvprintw(1,2,"#            Server                          Source                      Cost");
  1407.  
  1408.     sprintf(fstr,"%%03d:   [%%20.20s]  %%-%d.%ds %%16.16s",COLS-49,COLS-49);
  1409.     k = 1;
  1410.     for (asource = Sources; asource != NULL ; asource = asource->nextSource) {
  1411.  
  1412.         char tmpstr[STRINGSIZE];
  1413.         char cost_str[STRINGSIZE];
  1414.  
  1415.         current_s=asource->thisSource;
  1416.         tmpstr[0]='\0';
  1417.         if (strstr(current_s->name,".src")!=NULL) 
  1418.             strncat(tmpstr, current_s->name, strlen(current_s->name)-4);
  1419.         else
  1420.             strcat(tmpstr, current_s->name);
  1421.  
  1422.         format_source_cost(cost_str,current_s);
  1423.         sprintf(select_line[k], fstr, k, current_s->server, tmpstr, cost_str);
  1424.         source_selected(Selected_Sources,current_s,k);
  1425.         k++;
  1426.     }
  1427.     selection = source_selection;
  1428.     current_page = -1;
  1429.     max_selection=source_count;
  1430.     page_length= MINIMUM(LINES-6, source_count);
  1431.     selection_display(NOSELECTION);
  1432.  
  1433.     mvprintw(LINES-3,0,"Keywords:");
  1434.     mvprintw(LINES-3,10,"%s",question->keywords);
  1435.     refresh();
  1436. }
  1437.  
  1438. programstate
  1439. source_state(question)
  1440. Question question;
  1441. {
  1442.     int miss,k;
  1443.     /* int source_count; */
  1444.     /* Source current_s; */
  1445.     SList asource;
  1446.     char user_key[STRINGSIZE];
  1447.     char digit_str[STRINGSIZE];
  1448.     char message[STRINGSIZE];
  1449.  
  1450.     /* source_count = listlength((List)Sources); */
  1451.     selection_display(selection);
  1452.  
  1453.     digit_str[0]='\0';
  1454.  
  1455.     while(TRUE) {
  1456.  
  1457.         display_prompt("<space> selects, w for keywords, arrows move, <return> searches, q quits, or ?");
  1458.         user_key[0]=getch();
  1459.         switch(user_key[0]) {
  1460.  
  1461.         case 'H' :
  1462.             show_swais_history();
  1463.             state=UNKNOWN;
  1464.             return(GETSOURCES);
  1465.  
  1466.         case 'h' :
  1467.             ;
  1468.         case '?' :
  1469.             show_source_entry_help();
  1470.             state=UNKNOWN;
  1471.             return(GETSOURCES);
  1472.  
  1473.             /* forgive me: hardwired arrow keys for vt100 since we're
  1474.                                                                                    not using SysV curses and bsd curses lacks key support  */
  1475.         case '\033' :
  1476.             user_key[1]=getch();
  1477.             user_key[2]=getch();
  1478.             user_key[3]='\0';
  1479.         if ((strcmp(user_key, "\033[A") == 0) ||
  1480.         (strcmp(user_key, "\033OA") == 0)) {
  1481.                 selection_display(selection-1);
  1482.                 source_selection = selection;
  1483.                 break;
  1484.             }
  1485.  
  1486.         if ((strcmp(user_key, "\033[B") == 0) ||
  1487.         (strcmp(user_key, "\033OB") == 0)) {
  1488.                 selection_display(selection+1);
  1489.                 source_selection = selection;
  1490.                 break;
  1491.             }
  1492.  
  1493.         /* emacs <meta>v or left arrow = page previous */
  1494.         if (user_key[1]=='v' ||
  1495.         (strcmp(user_key, "\033[D") == 0) ||
  1496.         (strcmp(user_key, "\033OD") == 0)) {
  1497.                 selection_display(selection-page_length);
  1498.                 source_selection = selection;
  1499.                 break;
  1500.             }
  1501.  
  1502.         /* right arrow = page next */
  1503.         if ((strcmp(user_key, "\033[C") == 0) ||
  1504.         (strcmp(user_key, "\033OC") == 0)) {
  1505.           selection_display(selection+page_length);
  1506.           source_selection = selection;
  1507.           break;
  1508.         }
  1509.  
  1510.             break;
  1511.  
  1512.         case 'o' :
  1513.             return(GETOPTIONS);
  1514.  
  1515.         case ',' :
  1516.             ;
  1517.         case 'v' :
  1518.             k = 0;
  1519.             for (asource = Sources; 
  1520.  asource != NULL ; asource = asource->nextSource) {
  1521.                     k++;
  1522.                 if (k==selection) break;
  1523.             }
  1524.             view_source_info(Selected_Sources,asource->thisSource); 
  1525.             state=UNKNOWN;
  1526.             return(GETSOURCES);
  1527.  
  1528.         case 'X' :
  1529.             ;
  1530.         case '-' :
  1531.             k = 0;
  1532.             for (asource = Sources; 
  1533.  asource != NULL ; asource = asource->nextSource) {
  1534.                     k++;
  1535.                 if (k==selection) break;
  1536.             }
  1537.             sprintf(fpath,"%s%s.src", sdir, firstphrase(trim_junk(asource->thisSource->name)));
  1538.             PrintStatus(STATUS_URGENT, STATUS_HIGH,
  1539.             "Removing Source: %s\n", firstphrase(trim_junk(asource->thisSource->name)));
  1540.  
  1541.             if (unlink(fpath)==0) { 
  1542.                 if (FindSource(Selected_Sources,asource->thisSource->name)) {
  1543.  
  1544.                     Selected_Sources = DeleteSource(Selected_Sources,asource->thisSource);
  1545.                     question->numsources--;
  1546.                     question->modified=TRUE;
  1547.                 }
  1548.                 FreeSources(Sources);
  1549.                 Sources = NULL;
  1550.                 ReadSourceDirectory(sdir,TRUE);
  1551.                 ReadSourceDirectory(cdir,TRUE);
  1552.                 state=UNKNOWN;
  1553.                 return(GETSOURCES);
  1554.             }
  1555.             PrintStatus(STATUS_URGENT, STATUS_HIGH,
  1556.             "Unable to remove common sources");
  1557.             break;
  1558.  
  1559.         case '/' :
  1560.             user_key[0] = '\0';
  1561.             mvprintw(LINES-3,0,"Source Name: ");
  1562.             get_input_string(user_key);
  1563.             standend();
  1564.             mvprintw(LINES-3,0," ");
  1565.             clrtoeol();
  1566.             refresh();
  1567.             if (strlen(user_key)) {
  1568.                 k=0; 
  1569.                 miss = TRUE;
  1570.                 for (asource = Sources; 
  1571.  asource != NULL ; asource = asource->nextSource) {
  1572.                         k++;
  1573.                     if (asource->thisSource != NULL) 
  1574.                         if (!strncasecmp(user_key,
  1575.                         asource->thisSource->name, strlen(user_key))) {
  1576.                             selection_display(k);
  1577.                             source_selection = k;
  1578.                             miss = FALSE;
  1579.                             break;
  1580.                         }
  1581.                 }
  1582.                 if (miss) 
  1583.           PrintStatus(STATUS_URGENT, STATUS_HIGH,
  1584.                   "Unable to find source");
  1585.             }
  1586.             break;
  1587.  
  1588.         case '=' :
  1589.             k = 0;
  1590.             for (asource = Sources; 
  1591.  asource != NULL ; asource = asource->nextSource) {
  1592.                     k++;
  1593.                 if (FindSource(Selected_Sources,
  1594.                 asource->thisSource->name)) {
  1595.  
  1596.                     Selected_Sources = DeleteSource(Selected_Sources,asource->thisSource);
  1597.                     question->numsources--;
  1598.                     question->modified=TRUE;
  1599.                     display_source_selected(Selected_Sources,asource->thisSource);
  1600.                     source_selected(Selected_Sources,asource->thisSource,k);
  1601.                     selection_display(k);
  1602.                 }
  1603.             }
  1604.             break;
  1605.  
  1606.         case '.' :
  1607.             ;
  1608.         case ' ' :
  1609.             k = 0;
  1610.             for (asource = Sources; 
  1611.  asource != NULL ; asource = asource->nextSource) {
  1612.                     k++;
  1613.                 if (k==selection) break;
  1614.             }
  1615.             if (FindSource(Selected_Sources,asource->thisSource->name)) {
  1616.  
  1617.                 Selected_Sources = DeleteSource(Selected_Sources,asource->thisSource);
  1618.                 question->numsources--;
  1619.                 question->modified=TRUE;
  1620.             }
  1621.             else {
  1622.                 Selected_Sources = AddSource(Selected_Sources,asource->thisSource);
  1623.                 question->numsources++;
  1624.                 question->modified=TRUE;
  1625.             }
  1626.             display_source_selected(Selected_Sources,asource->thisSource);
  1627.             source_selected(Selected_Sources,asource->thisSource,selection);
  1628.             selection_display(selection);
  1629.             break;
  1630.  
  1631.         case 14 :
  1632.             ;
  1633.         case 'j' :
  1634.             selection_display(selection+1);
  1635.             source_selection = selection;
  1636.             break;
  1637.  
  1638.         case 16 :
  1639.             ;
  1640.         case 'k' :
  1641.             selection_display(selection-1);
  1642.             source_selection = selection;
  1643.             break;
  1644.         case 'q' :
  1645.             return(LEAVEPROGRAM);
  1646.         case 'r' :
  1647.             if(question->numresdocs > 0) return(SHOWRESULTS);
  1648.             break;
  1649.         case 's' :
  1650.             return(GETSOURCES);
  1651.         case 'R':
  1652.             return(RELDOCS);
  1653.         case 10 :
  1654.             k = 0;
  1655.             for (asource = Sources; 
  1656.  asource != NULL ; asource = asource->nextSource) {
  1657.                     k++;
  1658.                 if (k==selection) break;
  1659.             }
  1660.             if (NULL == FindSource(Selected_Sources,asource->thisSource)) {
  1661.  
  1662.                 Selected_Sources = AddSource(Selected_Sources,asource->thisSource);
  1663.                 question->numsources++;
  1664.                 question->modified=TRUE;
  1665.             }
  1666.             display_source_selected(Selected_Sources,asource->thisSource);
  1667.             source_selected(Selected_Sources,asource->thisSource,selection);
  1668.             selection_display(selection);
  1669.             return(nextstate(question)); 
  1670.  
  1671.         case 'w' :
  1672.             return(GETKEYWORDS);
  1673.  
  1674.         case 18 :
  1675.             ;
  1676.         case '\f' :
  1677.             wrefresh(curscr);
  1678.             break;
  1679.  
  1680.         case 4 :
  1681.             ;
  1682.         case 22 :
  1683.             ; /* ctrl-v */
  1684.         case 'J' :
  1685.             selection_display(selection+page_length);
  1686.             source_selection = selection;
  1687.             break;
  1688.  
  1689.         case 21 :
  1690.             ;
  1691.         case 'K' :
  1692.             selection_display(selection-page_length);
  1693.             source_selection = selection;
  1694.             break;
  1695.  
  1696.         default :
  1697.             if (isdigit(user_key[0])) {
  1698.                 digit_str[0] = user_key[0];
  1699.                 digit_str[1] = '\0';
  1700.                 mvprintw(LINES-3,0,"Source Number: ");
  1701.                 get_input_string(digit_str);
  1702.                 if (atoi(digit_str)!= 0) {
  1703.                     selection_display(atoi(digit_str));
  1704.                 }
  1705.                 standend();
  1706.                 mvprintw(LINES-3,0," ");
  1707.                 clrtoeol();
  1708.                 mvprintw(LINES-3,0,"Keywords:");
  1709.                 mvprintw(LINES-3,10,"%s",question->keywords);
  1710.             }
  1711.         }
  1712.     }
  1713. }
  1714.  
  1715. void
  1716. mail_command(question)
  1717. Question question;
  1718. {
  1719.     char tmpstr[STRINGSIZE];
  1720.     display_prompt("Enter your e-mail address; ^C to cancel");
  1721.     standout();
  1722.     tmpstr[0]='\0';
  1723.     strcat(tmpstr,"mail ");
  1724.     mvprintw(LINES-3,0,"Address:");
  1725.     standend();
  1726.     move(LINES-3,9);
  1727.     if (get_input_string(command)) {
  1728.         standend();
  1729.         mvprintw(LINES-3,0,"Address:");
  1730.         refresh();
  1731.         strcat(tmpstr,command);
  1732.         mvprintw(LINES-2,0,tmpstr);
  1733.         PipeWaisDocument(question, findDoc(question->ResultDocuments,selection-1),tmpstr);
  1734.         cbreak();
  1735.         screenstart();
  1736.     }
  1737.     standend();
  1738.     mvprintw(LINES-3,0,"\n");
  1739.     display_prompt("");
  1740.     refresh();
  1741. }
  1742.  
  1743.  
  1744. void
  1745. pipe_command(question)
  1746. Question question;
  1747. {
  1748.     display_prompt("Enter the command to be executed on this item; ^C to cancel");
  1749.     standout();
  1750.     mvprintw(LINES-3,0,"Command:");
  1751.     standend();
  1752.     move(LINES-3,9);
  1753.     if (get_input_string(command)) {
  1754.         standend();
  1755.         mvprintw(LINES-3,0,"Command:");
  1756.         refresh();
  1757.         PipeWaisDocument(question, findDoc(question->ResultDocuments,selection-1),command);
  1758.         cbreak();
  1759.         noecho();
  1760.         PrintStatus(STATUS_URGENT, STATUS_HIGH, "Press any key to continue"); 
  1761.         getch();
  1762.         cbreak();
  1763.         screenstart();
  1764.     }
  1765.     standend();
  1766.     mvprintw(LINES-3,0,"\n");
  1767.     display_prompt("");
  1768.     refresh();
  1769. }
  1770. void
  1771. save_command(question)
  1772. Question question;
  1773. {
  1774.     char cbuffer[100];
  1775.  
  1776.     display_prompt("Enter the filename into which to save this item; ^C to cancel");
  1777.     standout();
  1778.     mvprintw(LINES-3,0,"File:");
  1779.     standend();
  1780.     move(LINES-3,6);
  1781.     if (get_input_string(command)) {
  1782.         standend();
  1783.         mvprintw(LINES-3,0,"File:");
  1784.         refresh();
  1785.         sprintf(cbuffer,"cat >> %s",command);
  1786.         PipeWaisDocument(question, findDoc(question->ResultDocuments,selection-1),cbuffer);
  1787.         cbreak();
  1788.         noecho();
  1789.         PrintStatus(STATUS_URGENT, STATUS_HIGH, "Press any key to continue");
  1790.         getch();
  1791.         cbreak();
  1792.         screenstart();
  1793.     }
  1794.     standend();
  1795.     mvprintw(LINES-3,0,"\n");
  1796.     display_prompt("");
  1797.     refresh();
  1798. }
  1799.  
  1800. keyword_state(question)
  1801. Question question;
  1802. {
  1803.     display_prompt("Enter keywords with spaces between them; <return> to search; ^C to cancel");
  1804.     standout();
  1805.     mvprintw(LINES-3,0,"Keywords:");
  1806.     standend();
  1807.     move(LINES-3,10);
  1808.     strcpy(keywords,question->keywords);
  1809.     if (get_input_string(keywords)) {
  1810.         standend();
  1811.         mvprintw(LINES-3,0,"Keywords:");
  1812.         refresh();
  1813.         strcpy(question->keywords,keywords);
  1814.         question->modified = TRUE;
  1815.         return(MAKEQUERY);
  1816.     }
  1817.     standend();
  1818.     mvprintw(LINES-3,0,"Keywords:");
  1819.     mvprintw(LINES-3,10,"%s",question->keywords);
  1820.     refresh();
  1821.     return(GETSOURCES);
  1822. }
  1823. void
  1824. docs_screen(question)
  1825. Question question;
  1826. {
  1827.     DocList doclist;
  1828.     DocumentID current_doc;
  1829.     int k;
  1830.     int doc_count;
  1831.     char fstr[STRINGSIZE];
  1832.     char *sourcename;
  1833.  
  1834.     doc_count = listlength((List)Mydocs);
  1835.     title_display("Rel. Documents","Items:", doc_count);
  1836.     if (option_widetitles==FALSE) {
  1837.         mvprintw(1,2,"#    Score     Source                       Title Lines");
  1838.         sprintf(fstr,"%%03d:   [%%4d] (%%15.15s)  %%-%d.%ds %%5ld\n",COLS-40,COLS-40);
  1839.     }
  1840.     else {
  1841.         mvprintw(1,2,"#    Score                               Title Lines");
  1842.         sprintf(fstr,"%%03d:   [%%4d]  %%-%d.%ds %%5ld\n",COLS-22,COLS-22);
  1843.     }
  1844.  
  1845.     if (Mydocs != NULL) {
  1846.         k = 1;
  1847.         for ( doclist = Mydocs; doclist != NULL ;
  1848.  doclist = doclist->nextDoc) {
  1849.  
  1850.             current_doc = doclist->thisDoc;
  1851.             if (current_doc != NULL) {
  1852.                 sourcename = firstphrase(trim_junk(current_doc->doc->source));
  1853.                 if (NULL != strrchr(sourcename,'/')) {
  1854.                     sourcename = (char*)strrchr(sourcename,'/');
  1855.                     sourcename++;
  1856.                 }
  1857.                 if (option_widetitles==TRUE)
  1858.                     sprintf(select_line[k],fstr, k, current_doc->rawScore,
  1859.                     firstphrase(trim_junk(current_doc->doc->headline)),
  1860.                     current_doc->doc->numLines);
  1861.                 else
  1862.                     sprintf(select_line[k],fstr, k, current_doc->rawScore, sourcename,
  1863.                 firstphrase(trim_junk(current_doc->doc->headline)),
  1864.                 current_doc->doc->numLines);
  1865.                 k++;
  1866.             }
  1867.         }
  1868.     }
  1869.     selection = relevant_selection; 
  1870.     current_page = -1;
  1871.     max_selection=doc_count;
  1872.     page_length= MINIMUM(LINES-6, doc_count);
  1873.     selection_display(NOSELECTION);
  1874. }
  1875.  
  1876. void
  1877. result_screen(question)
  1878. Question question;
  1879. {
  1880.     DocList doclist;
  1881.     DocumentID current_doc;
  1882.     int k;
  1883.     int doc_count;
  1884.     char fstr[STRINGSIZE];
  1885.     char *sourcename;
  1886.  
  1887.     doc_count = question->numresdocs;
  1888.  
  1889.     title_display("Search Results","Items:", doc_count);
  1890.  
  1891.     if (option_widetitles==FALSE) {
  1892.         mvprintw(1,2,"#    Score     Source                       Title                       Lines");
  1893.         sprintf(fstr,"%%03d:   [%%4d] (%%15.15s)  %%-%d.%ds %%5ld\n",COLS-40,COLS-40);
  1894.     }
  1895.     else {
  1896.         mvprintw(1,2,"#    Score                               Title                          Lines");
  1897.         sprintf(fstr,"%%03d:   [%%4d]  %%-%d.%ds %%5ld\n",COLS-22,COLS-22);
  1898.     }
  1899.  
  1900.     if (question->ResultDocuments != NULL) {
  1901.         k = 1;
  1902.         for ( doclist = question->ResultDocuments; doclist != NULL ;
  1903.  doclist = doclist->nextDoc) {
  1904.  
  1905.             current_doc = doclist->thisDoc;
  1906.             if (current_doc != NULL) {
  1907.                 sourcename = firstphrase(trim_junk(current_doc->doc->source));
  1908.                 if (NULL != strrchr(sourcename,'/')) {
  1909.                     sourcename = (char*)strrchr(sourcename,'/');
  1910.                     sourcename++;
  1911.                 }
  1912.                 if (option_widetitles==TRUE) 
  1913.                     sprintf(select_line[k],fstr, k, current_doc->rawScore, 
  1914.                     firstphrase(trim_junk(current_doc->doc->headline)),
  1915.                     current_doc->doc->numLines);
  1916.                 else 
  1917.                     sprintf(select_line[k],fstr, k, current_doc->rawScore, sourcename,
  1918.                     firstphrase(trim_junk(current_doc->doc->headline)),
  1919.                     current_doc->doc->numLines);
  1920.                 k++;
  1921.             }
  1922.         }
  1923.     }
  1924.     selection = result_selection;
  1925.     current_page = -1;
  1926.     max_selection=doc_count;
  1927.     page_length= MINIMUM(LINES-6, doc_count);
  1928.     selection_display(NOSELECTION);
  1929. }
  1930. programstate
  1931. docs_state(question)
  1932. Question question;
  1933. {
  1934.  
  1935.     DocList doclist;
  1936.     DocumentID current_doc;
  1937.     char user_key[STRINGSIZE];
  1938.     char digit_str[STRINGSIZE];
  1939.     int k,miss,tmpval;
  1940.  
  1941.     selection_display(selection);
  1942.  
  1943.     digit_str[0]='\0';
  1944.     while(TRUE) {
  1945.         display_prompt("<space> selects, arrows move, w keywords, r results, s sources, ? for help");
  1946.         user_key[0]=getch();
  1947.         switch(user_key[0]) {
  1948.  
  1949.         case 'q':
  1950.             return(LEAVEPROGRAM);
  1951.         case '\033' :
  1952.             user_key[1]=getch();
  1953.             user_key[2]=getch();
  1954.             user_key[3]='\0';
  1955.         if ((strcmp(user_key, "\033[A") == 0) ||
  1956.         (strcmp(user_key, "\033OA") == 0)){
  1957.                 selection_display(selection-1);
  1958.                 relevant_selection = selection;
  1959.                 break;
  1960.             }
  1961.         if ((strcmp(user_key, "\033[B") == 0) ||
  1962.         (strcmp(user_key, "\033OB") == 0)) {
  1963.                 selection_display(selection+1);
  1964.                 relevant_selection = selection;
  1965.                 break;
  1966.             }
  1967.         /* emacs <meta>v or left arrow = page previous */
  1968.         if (user_key[1]=='v' ||
  1969.         (strcmp(user_key, "\033[D") == 0) ||
  1970.         (strcmp(user_key, "\033OD") == 0)) {
  1971.                 selection_display(selection-page_length);
  1972.                 relevant_selection = selection;
  1973.                 break;
  1974.             }
  1975.  
  1976.         /* right arrow = page next */
  1977.         if ((strcmp(user_key, "\033[C") == 0) ||
  1978.         (strcmp(user_key, "\033OC") == 0)) {
  1979.           selection_display(selection+page_length);
  1980.           relevant_selection = selection;
  1981.           break;
  1982.         }
  1983.  
  1984.         case 'X':
  1985.             tmpval=freeRelDoc(Mydocs,relevant_selection-1);
  1986.             state=UNKNOWN;
  1987.             if(tmpval)
  1988.                 return(RELDOCS);
  1989.             else
  1990.                 return(GETKEYWORDS);
  1991.  
  1992.         case 'D':/* delete all relevant docs */
  1993.             freeDocList(Mydocs);
  1994.             Mydocs=NULL;
  1995.             selection = -1;
  1996.             relevant_selection=1;
  1997.             return(GETKEYWORDS); 
  1998.  
  1999.         case 'o' :
  2000.             return(GETOPTIONS);
  2001.  
  2002.         case 's' :
  2003.             return(GETSOURCES);
  2004.         case 'w' :
  2005.             return(GETKEYWORDS);
  2006.         case 'r':
  2007.             return(SHOWRESULTS);
  2008.         case 'H' :
  2009.             show_swais_history();
  2010.             state=UNKNOWN;
  2011.             return(RELDOCS);
  2012.  
  2013.         case 'h' :
  2014.             ;
  2015.         case '?' :
  2016.             show_relevant_help();
  2017.             state=UNKNOWN;
  2018.             return(RELDOCS);
  2019.  
  2020.         case 14 :
  2021.             ;
  2022.         case 'j' :
  2023.             selection_display(selection+1);
  2024.             relevant_selection = selection;
  2025.             break;
  2026.  
  2027.         case 16 :
  2028.             ;
  2029.         case 'k' :
  2030.             selection_display(selection-1);
  2031.             relevant_selection = selection;
  2032.             break;
  2033.  
  2034.         default :
  2035.             if (isdigit(user_key[0])) {
  2036.                 digit_str[0] = user_key[0];
  2037.                 digit_str[1] = '\0';
  2038.                 mvprintw(LINES-3,0,"Item Number: ");
  2039.                 get_input_string(digit_str);
  2040.                 if (atoi(digit_str)!= 0) {
  2041.                     selection_display(atoi(digit_str));
  2042.                     relevant_selection = selection;
  2043.                 }
  2044.                 standend();
  2045.                 mvprintw(LINES-3,0," ");
  2046.                 clrtoeol();
  2047.             }
  2048.         }
  2049.     }
  2050. }
  2051. programstate
  2052. result_state(question)
  2053. Question question;
  2054. {
  2055.  
  2056.     DocList doclist;
  2057.     DocumentID current_doc;
  2058.     char user_key[STRINGSIZE];
  2059.     char digit_str[STRINGSIZE];
  2060.     int k,miss;
  2061.  
  2062.     selection_display(selection);
  2063.  
  2064.     digit_str[0]='\0';
  2065.     while(TRUE) {
  2066.         display_prompt("<space> selects, arrows move, w for keywords, s for sources, ? for help");
  2067.         user_key[0]=getch();
  2068.         switch(user_key[0]) {
  2069.  
  2070.         case 'H' :
  2071.             show_swais_history();
  2072.             state=UNKNOWN;
  2073.             return(SHOWRESULTS);
  2074.  
  2075.         case 'h' :
  2076.             ;
  2077.         case '?' :
  2078.             show_search_results_help();
  2079.             state=UNKNOWN;
  2080.             return(SHOWRESULTS);
  2081.  
  2082.             /* forgive me: hardwired arrow keys for vt100 since we're
  2083.                                                                              not using SysV curses and bsd curses lacks key support  */
  2084.         case '\033' :
  2085.             user_key[1]=getch();
  2086.             user_key[2]=getch();
  2087.             user_key[3]='\0';
  2088.             if ((strcmp(user_key, "\033[A") == 0) ||
  2089.                 (strcmp(user_key, "\033OA") == 0)) {
  2090.                 selection_display(selection-1);
  2091.                 result_selection = selection;
  2092.                 break;
  2093.             }
  2094.             if ((strcmp(user_key, "\033[B") == 0) ||
  2095.                 (strcmp(user_key, "\033OB") == 0)) {
  2096.                 selection_display(selection+1);
  2097.                 result_selection = selection;
  2098.                 break;
  2099.             }
  2100.         /* emacs <meta>v or left arrow = page previous */
  2101.             if (user_key[1]=='v' ||
  2102.         (strcmp(user_key, "\033[D") == 0) ||
  2103.                 (strcmp(user_key, "\033OD") == 0)) {
  2104.                 selection_display(selection-page_length);
  2105.                 result_selection = selection;
  2106.                 break;
  2107.             }
  2108.             /* right arrow = page next */
  2109.             if ((strcmp(user_key, "\033[C") == 0) ||
  2110.                 (strcmp(user_key, "\033OC") == 0)) {
  2111.                 selection_display(selection+page_length);
  2112.                 result_selection = selection;
  2113.                 break;
  2114.           }
  2115.  
  2116.         case 'o' :
  2117.             return(GETOPTIONS);
  2118.  
  2119.         case ',' :
  2120.             ;
  2121.         case 'v' :
  2122.             view_result_info(findDoc(question->ResultDocuments,selection-1));
  2123.             state=UNKNOWN;
  2124.             return(SHOWRESULTS);
  2125.         case 'V':
  2126.             break;
  2127.  
  2128.         case 'u' :
  2129.             UseWaisDocument(question, findDoc(question->ResultDocuments,selection-1));
  2130.             break;
  2131.  
  2132.         case 10 :
  2133.             ;
  2134.         case ' ' :
  2135.       DisplayWaisDocument(question,
  2136.       findDoc(question->ResultDocuments,selection-1));
  2137. /*
  2138.             PipeWaisDocument(question, 
  2139.             findDoc(question->ResultDocuments,selection-1), 
  2140.             "${PAGER-more}");
  2141.             if (option_pagerpause==TRUE) {
  2142.                 cbreak();
  2143.                 noecho();
  2144.                 PrintStatus(STATUS_URGENT, STATUS_HIGH, 
  2145.                 "Press any key to continue"); 
  2146.                 getch();
  2147.             }
  2148. */
  2149.             screenstart();
  2150.             state=UNKNOWN;
  2151.             return(SHOWRESULTS);
  2152.         case 'S':
  2153.             save_command(question);
  2154.             state=UNKNOWN;
  2155.             return(SHOWRESULTS);
  2156.             break;
  2157.         case 'R':
  2158.             return(RELDOCS);
  2159.         case 'r':
  2160.             AddDocAsRelevant(findDoc(question->ResultDocuments,selection-1));
  2161.             state=UNKNOWN;
  2162.             break;
  2163. #ifndef SECURECLIENT
  2164.         case '|' :
  2165.             ;
  2166.         case 'c' :
  2167.             pipe_command(question);
  2168.             state=UNKNOWN;
  2169.             return(SHOWRESULTS);
  2170. #endif
  2171.         case 14 :
  2172.             ;
  2173.         case 'j' :
  2174.             selection_display(selection+1); 
  2175.             result_selection = selection;
  2176.             break;
  2177.  
  2178.         case 16 :
  2179.             ;
  2180.         case 'k' :
  2181.             selection_display(selection-1); 
  2182.             result_selection = selection;
  2183.             break;
  2184.  
  2185.         case 'q' :
  2186.             return(LEAVEPROGRAM);
  2187.         case 's' :
  2188.             return(GETSOURCES);
  2189.         case 'w' :
  2190.             return(GETKEYWORDS);
  2191.  
  2192.         case 18 :
  2193.             ;
  2194.         case '\f' :
  2195.             wrefresh(curscr);
  2196.             break;
  2197.  
  2198.  
  2199.         case '/' :
  2200.             user_key[0] = '\0';
  2201.             mvprintw(LINES-3,0,"Item Name: ");
  2202.             get_input_string(user_key);
  2203.             standend();
  2204.             mvprintw(LINES-3,0," ");
  2205.             clrtoeol();
  2206.             refresh();
  2207.             if (strlen(user_key)) {
  2208.                 k=0; 
  2209.                 miss = TRUE;
  2210.                 for ( doclist = question->ResultDocuments; 
  2211.  doclist != NULL ; doclist = doclist->nextDoc) {
  2212.                         current_doc = doclist->thisDoc;
  2213.                     k++;
  2214.                     if (current_doc != NULL)
  2215.                         if (!strncasecmp(user_key,current_doc->doc->headline,
  2216.                         strlen(user_key))) {
  2217.                             selection_display(k);
  2218.                             result_selection = k;
  2219.                             miss = FALSE;
  2220.                             break;
  2221.                         }
  2222.                 }
  2223.                 if (miss) 
  2224.           PrintStatus(STATUS_URGENT, STATUS_HIGH, 
  2225.                   "Unable to find item");
  2226.             }
  2227.             break;
  2228.  
  2229.         case 'm' :
  2230.             mail_command(question);
  2231.             state=UNKNOWN;
  2232.             return(SHOWRESULTS);
  2233.  
  2234.         case 4 :
  2235.             ;
  2236.         case 22 :
  2237.             ; /* emacs ctrl-v */
  2238.         case 'J' :
  2239.             selection_display(selection+page_length);
  2240.             result_selection = selection;
  2241.             break;
  2242.  
  2243.         case 21 :
  2244.             ;
  2245.         case 'K' :
  2246.             selection_display(selection-page_length); 
  2247.             result_selection = selection;
  2248.             break;
  2249.  
  2250.         default :
  2251.             if (isdigit(user_key[0])) {
  2252.                 digit_str[0] = user_key[0];
  2253.                 digit_str[1] = '\0';
  2254.                 mvprintw(LINES-3,0,"Item Number: ");
  2255.                 get_input_string(digit_str);
  2256.                 if (atoi(digit_str)!= 0) {
  2257.                     selection_display(atoi(digit_str));
  2258.                     result_selection = selection;
  2259.                 }
  2260.                 standend();
  2261.                 mvprintw(LINES-3,0," ");
  2262.                 clrtoeol();
  2263.             }
  2264.         }
  2265.     }
  2266. }
  2267.  
  2268. void
  2269. main(argc, argv)
  2270. int argc;
  2271. char **argv;
  2272. {
  2273.     Question question;
  2274.     SList asource;
  2275.     char msg[STRINGSIZE];
  2276.     char *getenv();
  2277.     char sourcename[STRINGSIZE];
  2278.     int i,doc_count, maxDocs;
  2279.  
  2280.     /*Mydocs=makeDocList(NULL,NULL);*/
  2281.     if (command_name = (char*)rindex(argv[0], '/'))
  2282.         command_name++;
  2283.     else
  2284.         command_name = argv[0];
  2285.  
  2286.     command[0]='\0';
  2287.  
  2288.     sdir = cdir = NULL;
  2289.     keywords[0] = 0;
  2290.     sourcename[0] = 0;
  2291.  
  2292.     maxDocs = 40;
  2293.  
  2294.     i = 1;
  2295.     for(; i < argc; i++) {
  2296.         if (*argv[i] == '-') {
  2297.             argv[i]++;
  2298.             switch (*argv[i]) {
  2299.             case 'C':
  2300.                 i++;
  2301.                 if(i >= argc) {
  2302.                     fprintf(stderr, "Too few arguments: common source directory missing.\n");
  2303.                     exit(1);
  2304.                 }
  2305.                 cdir = argv[i];
  2306.                 break;
  2307.             case 'S':
  2308.                 i++;
  2309.                 if(i >= argc) {
  2310.                     fprintf(stderr, "Too few arguments: user source directory missing.\n");
  2311.                     exit(1);
  2312.                 }
  2313.                 sdir = argv[i];
  2314.                 break;
  2315.             case 's':
  2316.                 i++;
  2317.                 if(i >= argc) {
  2318.                     fprintf(stderr, "Too few arguments: source name missing.\n");
  2319.                     exit(1);
  2320.                 }
  2321.                 sprintf(sourcename,"%s.src", argv[i]);
  2322.                 break;
  2323.             case 'h':
  2324.                 usage(argv[0]);
  2325.                 exit(0);
  2326.                 break;
  2327.             default:
  2328.                 fprintf(stderr, "Unknown option: %s.\n", argv[i]);
  2329.                 exit(1);
  2330.             }
  2331.         }
  2332.         else {
  2333.             if((strlen(keywords) + strlen(argv[i]) + 1) < STRINGSIZE) {
  2334.                 if (strlen(keywords)) strcat(keywords, " ");
  2335.                 strcat(keywords, argv[i]);
  2336.             }
  2337.         }
  2338.     }
  2339.  
  2340.     if(sdir == NULL) {
  2341.         if((sdir = getenv("WAISSOURCEDIR")) == NULL) {
  2342.             sprintf(msg, "%s/wais-sources/", getenv("HOME"));
  2343.             sdir = s_strdup(msg);
  2344.         }
  2345.     }
  2346.     sdir = fixdirname(sdir);
  2347.     ReadSourceDirectory(sdir, TRUE);
  2348.  
  2349.     if(cdir == NULL) {
  2350.         if((cdir = getenv("WAISCOMMONSOURCEDIR")) == NULL) {
  2351.             strcpy(msg, COMMON_SOURCE_DIR);
  2352.             cdir = s_strdup(msg);
  2353.         }
  2354.     }
  2355.     cdir = fixdirname(cdir);
  2356.     ReadSourceDirectory(cdir, TRUE);
  2357.  
  2358.     Refresh_sources();
  2359.  
  2360.     strcpy(options[1].name, "widetitles");
  2361.     strcpy(options[1].desc, "Show wide Item titles on Results Screen by omitting source name"); 
  2362.     options[1].type = OPTION_BOOLEAN;
  2363.     options[1].var.intptr = &option_widetitles;
  2364.     options[1].update = null;
  2365.  
  2366.     strcpy(options[2].name, "sortsources");
  2367.     strcpy(options[2].desc, "Display sources sorted alphabetically rather than directory order");
  2368.     options[2].type = OPTION_BOOLEAN;
  2369.     options[2].var.intptr = &option_sortsources;
  2370.     options[2].update = Refresh_sources;
  2371.  
  2372.     strcpy(options[3].name, "sourcedir");
  2373.     strcpy(options[3].desc, "Personal WAIS source directory containing *.src description files");
  2374.     options[3].type = OPTION_STRING;
  2375.     options[3].var.charptr = sdir;
  2376.     options[3].update = Refresh_sources;
  2377.  
  2378.     strcpy(options[4].name, "commondir");
  2379.     strcpy(options[4].desc, "Common WAIS source directory containing *.src description files");
  2380.     options[4].type = OPTION_STRING;
  2381.     options[4].var.charptr = cdir;
  2382.     options[4].update = Refresh_sources;
  2383.  
  2384.     strcpy(options[5].name, "pagerpause");
  2385.     strcpy(options[5].desc, "Pause after displaying a document via the external pager");
  2386.     options[5].type = OPTION_BOOLEAN;
  2387.     options[5].var.intptr = &option_pagerpause;
  2388.     options[5].update = null;
  2389.  
  2390.     strcpy(options[6].name, "maxitems");
  2391.     strcpy(options[6].desc, "Maximum items (documents) returned in a single query");
  2392.     options[6].type = OPTION_INTEGER;
  2393.     options[6].var.intptr = &maxDocs;
  2394.     options[6].update = null;
  2395.  
  2396.     question = (Question)s_malloc(sizeof(_Question));
  2397.     question->numsources=0;
  2398.     question->modified=FALSE;
  2399.  
  2400.     screenstart();
  2401.  
  2402.     state = UNKNOWN;
  2403.  
  2404.     if (sourcename[0] != 0)
  2405.         for(asource = Sources; asource != NULL; asource = asource->nextSource) 
  2406.             if (!strcmp(sourcename, asource->thisSource->name)) {
  2407.                 Selected_Sources = AddSource(Selected_Sources, asource->thisSource);
  2408.                 question->numsources++;
  2409.                 question->modified=TRUE;
  2410.             }
  2411.  
  2412.     if (keywords[0]!='\0') {
  2413.         strcpy(question->keywords,keywords);
  2414.         question->modified = TRUE;
  2415.     }
  2416.  
  2417.     new_state = nextstate(question);
  2418.  
  2419.     if (setjmp(main_env)!=0) {
  2420.         state=UNKNOWN;
  2421.         new_state=GETSOURCES;
  2422.     }
  2423.  
  2424.     while (TRUE) {
  2425.  
  2426.         if (new_state!=state) {
  2427.             if ((new_state /10) != (state /10)) {
  2428.                 clear();
  2429.                 switch (new_state) {
  2430.                 case GETSOURCES:
  2431.                     ;
  2432.                 case GETKEYWORDS:
  2433.                     ;
  2434.                 case MAKEQUERY:
  2435.                     source_screen(question); 
  2436.                     break;
  2437.                 case SHOWRESULTS:
  2438.                     result_screen(question); 
  2439.                     break;
  2440.                 case GETOPTIONS :
  2441.                     option_screen(question); 
  2442.                     break;
  2443.                 case RELDOCS:
  2444.                     doc_count = listlength((List)Mydocs);
  2445.                     if(doc_count>0)
  2446.                         docs_screen(question);
  2447.                     else
  2448.                         source_screen(question);
  2449.                     break;
  2450.                 case LEAVEPROGRAM:
  2451.                     break; 
  2452.                 }
  2453.             }
  2454.             else {
  2455.                 selection_display(NOSELECTION);
  2456.                 display_prompt("");
  2457.             }
  2458.             state = new_state;
  2459.         }
  2460.  
  2461.         switch (state) {
  2462.  
  2463.         case MAKEQUERY:
  2464.             new_state = makequery_state(question);
  2465.             break;
  2466.  
  2467.         case GETKEYWORDS:
  2468.             ;
  2469.             new_state = keyword_state(question);
  2470.             break;
  2471.  
  2472.         case GETSOURCES:
  2473.             new_state = source_state(question);
  2474.             break;
  2475.  
  2476.         case SHOWRESULTS:
  2477.             new_state = result_state(question);
  2478.             break;
  2479.  
  2480.         case GETOPTIONS:
  2481.             new_state = option_state(question);
  2482.             break;
  2483.  
  2484.         case LEAVEPROGRAM:
  2485.             screenend();
  2486.             exit(0);
  2487.         case RELDOCS:
  2488.             doc_count = listlength((List)Mydocs);
  2489.             if(doc_count>0)
  2490.                 new_state=docs_state(question);
  2491.             else
  2492.                 new_state=source_state(question);
  2493.             break;
  2494.         }
  2495.     }
  2496. }
  2497.  
  2498.